package Framework;

import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class GUI extends JFrame implements Runnable, MouseListener,
		WindowListener {

	private JPanel fieldPanel;
	private String emptyField = ".";
	private String p1 = "X";
	private String p2 = "O";
	int mode = 1;
	private ArrayList<JButton> buttons = new ArrayList<JButton>();
	public Intelligence intel;

	@SuppressWarnings("rawtypes")
	private Constructor[] constr;

	private Settings s;

	private Main main;

	public GUI(int rows, int columns, String game, Main main, int mode) {
		this.main = main;
		this.mode = mode;

		addWindowListener(this);

		Class<?> gameClass = null;
		try {
			System.out.println("Deze hiero vanuit GUI: " + game);
			String tempFile = game + ".GameIntelligence";
			System.out.println("Dit bestand: " + tempFile);
			gameClass = Class.forName(game + ".GameIntelligence");
			constr = gameClass.getConstructors();
			try {
				intel = (Intelligence) constr[0].newInstance(rows, columns,
						"A", "B", main.side);
			} catch (IllegalArgumentException e) {
			} catch (InstantiationException e) {
			} catch (IllegalAccessException e) {
			} catch (InvocationTargetException e) {
			}
		} catch (ClassNotFoundException e1) {
			System.out.println("Class not found");
		}

		try {
			gameClass = Class.forName(game + ".GameSettings");
			constr = gameClass.getConstructors();
			s = (Settings) constr[0].newInstance();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		fieldPanel = new JPanel();

		fieldPanel.setLayout(new GridLayout(rows, columns));
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				JButton button = new JButton(emptyField);
				buttons.add(button);
				fieldPanel.add(button);
				if (mode != Intelligence.COMPUTER) {
					button.addMouseListener(this);
				}
			}
		}
		add(fieldPanel);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
		if (mode == Intelligence.COMPUTER) {
			new Thread(this).start();
		}
	}

	@Override
	public void windowActivated(WindowEvent arg0) {
	}

	@Override
	public void windowClosed(WindowEvent arg0) {
	}

	@Override
	public void windowClosing(WindowEvent arg0) {
		main.c.forfeit();
	}

	@Override
	public void windowDeactivated(WindowEvent arg0) {
	}

	@Override
	public void windowDeiconified(WindowEvent arg0) {
	}

	@Override
	public void windowIconified(WindowEvent arg0) {
	}

	@Override
	public void windowOpened(WindowEvent arg0) {
	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
	}

	@Override
	public void mousePressed(MouseEvent e) {
		if (main.yourTurn) {
			for (int i = 0; i < buttons.size(); i++) {
				if (e.getSource() == buttons.get(i)) {
					main.c.move(i);
				}
			}
		} else {
			JOptionPane.showMessageDialog(this, "Het is niet uw beurt.");
		}
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
	}

	public void playerMove(int move) {
		Stack<Integer> wbr = intel.willBeReplaced(move, main.side);
		intel.place(move / Intelligence.columns, move % Intelligence.rows,
				main.side);
		while (wbr.size() > 0) {
			int x = wbr.pop();
			JButton button = buttons.get(x);
			button.setText(p1);
		}
	}

	public void doMove(int move) {
		Stack<Integer> wbr = intel.willBeReplaced(move,
				(main.side == 0 ? 1 : 0));
		intel.place(move / Intelligence.columns, move % Intelligence.rows,
				(main.side == 0 ? 1 : 0));
		while (wbr.size() > 0) {
			int x = wbr.pop();
			JButton button = buttons.get(x);
			button.setText(p2);
		}
	}

	public void init(HashMap<Integer, Integer> inits) {
		for (int i = 0; i < buttons.size(); ++i) {
			if (inits.get(i) != 0) {
				if (main.side == 0) {
					if (inits.get(i) == 1) {
						buttons.get(i).setText(p1);
						intel.board[i / Intelligence.columns][i
								% Intelligence.columns] = main.side;
					} else {
						buttons.get(i).setText(p2);
						intel.board[i / Intelligence.columns][i
								% Intelligence.columns] = (main.side == 0 ? 1
								: 0);
					}
				}
				if (main.side == 1) {
					if (inits.get(i) == 2) {
						buttons.get(i).setText(p1);
						intel.board[i / Intelligence.columns][i
								% Intelligence.columns] = main.side;
					} else {
						buttons.get(i).setText(p2);
						intel.board[i / Intelligence.columns][i
								% Intelligence.columns] = (main.side == 0 ? 1
								: 0);
					}
				}
			}
		}
	}

	@Override
	public void run() {
		while (!intel.gameOver()) {
			if (main.yourTurn == true) {
				System.out.println("" + intel.toString());
				intel.side = main.side;
				Best best = intel.chooseMove(main.side, Intelligence.HUMAN_WIN,
						Intelligence.COMPUTER_WIN, 0);
				int m = best.row * Intelligence.columns + best.column;
				main.c.move(m);
			}
		}
	}
}